package com.treasure.mall.zbqmallapi.controller;

import com.alibaba.fastjson.JSONObject;
import com.treasure.mall.biz.bo.SystemInfoData;
import com.treasure.mall.biz.dto.condition.AfterSaleCondition;
import com.treasure.mall.biz.dto.condition.OrderSearchCondition;
import com.treasure.mall.biz.dto.order.AfterSaleSaveDTO;
import com.treasure.mall.biz.dto.order.DeliverDTO;
import com.treasure.mall.biz.dto.order.OrderSaveDTO;
import com.treasure.mall.biz.dto.order.OrderUpdateDTO;
import com.treasure.mall.biz.entity.order.AfterSaleBillPO;
import com.treasure.mall.biz.entity.order.DealOrderPO;
import com.treasure.mall.biz.entity.order.DeliverBillPO;
import com.treasure.mall.biz.entity.order.SubOrderPO;
import com.treasure.mall.biz.entity.pay.PaymentBillPO;
import com.treasure.mall.biz.entity.user.UserPO;
import com.treasure.mall.biz.remote.quickpay.WechatPayService;
import com.treasure.mall.biz.remote.quickpay.dto.WxTradeOrderDTO;
import com.treasure.mall.biz.remote.track.LogisticsProvider;
import com.treasure.mall.biz.service.core.blacklist.BlacklistService;
import com.treasure.mall.biz.service.core.order.AfterSaleService;
import com.treasure.mall.biz.service.core.order.DealOrderService;
import com.treasure.mall.biz.service.core.order.DeliverService;
import com.treasure.mall.biz.service.core.order.SubOrderService;
import com.treasure.mall.biz.service.core.pay.PayService;
import com.treasure.mall.biz.service.core.pay.PaymentBillService;
import com.treasure.mall.biz.vo.PageDataVO;
import com.treasure.mall.zbq.common.Jsr310Utils;
import com.treasure.mall.zbq.common.StringUtilsExt;
import com.treasure.mall.zbq.common.annotation.CurrentUser;
import com.treasure.mall.zbq.common.base.ApiResult;
import com.treasure.mall.zbq.common.base.ResultCodeEnum;
import com.treasure.mall.zbq.common.exception.ApiException;
import com.treasure.mall.zbq.common.ienum.SystemEnums;
import com.treasure.mall.zbq.common.ienum.order.OrderEnums;
import com.treasure.mall.zbq.common.oss.ResourceService;
import com.treasure.mall.zbqmallapi.annotation.AccessControl;
import com.treasure.mall.zbqmallapi.annotation.SystemInfo;
import com.treasure.mall.zbqmallapi.dto.CreateOrder;
import com.treasure.mall.zbqmallapi.mapstruct.OrderMapStruct;
import com.treasure.mall.zbqmallapi.vo.order.AfterSaleBillVO;
import com.treasure.mall.zbqmallapi.vo.order.LogisticsDataVO;
import com.treasure.mall.zbqmallapi.vo.order.LogisticsVO;
import com.treasure.mall.zbqmallapi.vo.order.SubOrderVO;
import com.treasure.mall.zbqmallapi.vo.product.GoodsInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * +---------------------------------------------------------
 * * @package: com.treasure.mall.zbqmallapi.controller
 * * @author: guomw (guomwchen@foxmail.com)
 * * @date: 2020/6/13 17:29
 * * @since: V1.0.0
 * +---------------------------------------------------------
 * 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的
 * Copyright 2019-2022 com.treasure.mall.zbqmallapi.controller Inc. All rights reserved.
 */
@Api(tags = "订单模块")
@RestController
@AccessControl(needLogin = true)
@RequestMapping("/order")
public class OrderController {
    @Resource
    private LogisticsProvider provider;
    @Resource
    private PayService payService;
    @Resource
    private DealOrderService dealOrderService;
    @Resource
    private SubOrderService subOrderService;
    @Resource
    private AfterSaleService afterSaleService;
    @Resource
    private ResourceService resourceService;
    @Resource
    private PaymentBillService paymentBillService;
    @Resource
    private DeliverService deliverService;
    @Resource
    private WechatPayService wechatPayService;
    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;
    @Autowired
    private BlacklistService blacklistService;

    /**
     * 创建订单
     *
     * @param user
     * @param request
     * @param createOrder
     * @return
     */
    @ApiOperation("创建订单")
    @PostMapping("/create")
    public ApiResult create(@CurrentUser UserPO user, HttpServletRequest request, @RequestBody CreateOrder createOrder, @SystemInfo SystemInfoData systemInfoData) {
        //检查是否是黑名单
        if (blacklistService.checkByUserId(user.getUserId(), SystemEnums.BlacklistType.CREATE_ORDER)) {
            return ApiResult.error(ResultCodeEnum.ILLEGAL_STATE, "检测到您的账号存在违规记录，已被系统自动拦截，禁止购买，请联系客服!");
        }

        OrderSaveDTO dto = new OrderSaveDTO();
        dto.setDeductBalance(createOrder.getBalancePay());
        dto.setNeedIdentify(createOrder.getEnableIdentification());
        dto.setUserId(user.getUserId());
        dto.setProductInfo(new String[]{createOrder.getProductInfo()});
        dto.setReceivingInfo(createOrder.getAddress().getReceivingInfo());
        dto.setUserMemo(createOrder.getComment());
        dto.setOrderType(OrderEnums.OrderType.NORMAL);
        if (createOrder.getOrderType() == 1) {
            dto.setAuctionSessionId(createOrder.getAuctionSessionId());
            dto.setOrderType(OrderEnums.OrderType.AUCTION);
        }
        dto.setLiveSessionId(createOrder.getLiveSessionId());
        dto.setExtendData(JSONObject.toJSONString(systemInfoData));
        DealOrderPO orderPO = dealOrderService.create(dto);

        //订单支付
        WxTradeOrderDTO tradeOrderDTO = payService.pay(orderPO);
        if (tradeOrderDTO == null) {
            Map<String, Object> map = new HashMap<>(1);
            map.put("wechatMini", null);
            return ApiResult.ok(map);
        }

        if (createOrder.getSource() != null && createOrder.getSource() == 1) {
            tradeOrderDTO.setTradeType(OrderEnums.TradeType.APP);
        }


        //支付超时
        taskScheduler.schedule(() -> payService.payTimeout(orderPO.getOrderId()), Jsr310Utils.DateTime.toDate(orderPO.getPayExpireTime()));

        return ApiResult.ok(wechatPayService.JsApiBizPackage(tradeOrderDTO, request));
    }

//    /**
//     * 修改订单信息
//     *
//     * @param updateDTO
//     * @return
//     */
//    @PostMapping("/update")
//    public ApiResult update(@RequestBody OrderUpdateDTO updateDTO) {
////        dealOrderService.updateOrder(updateDTO);
////        return ApiResult.ok();
//    }

    @PostMapping("/updateAndPay")
    public ApiResult updateAndPay(
            @RequestBody OrderUpdateDTO updateDTO,
            @RequestParam(required = false, defaultValue = "0") int source,
            HttpServletRequest request,
            @SystemInfo SystemInfoData systemInfoData
    ) {
        updateDTO.setExtendData(JSONObject.toJSONString(systemInfoData));
        DealOrderPO orderPO = dealOrderService.updateOrder(updateDTO);

        //订单支付
        WxTradeOrderDTO tradeOrderDTO = payService.pay(orderPO);
        if (tradeOrderDTO == null) {
            Map<String, Object> map = new HashMap<>(1);
            map.put("wechatMini", null);
            return ApiResult.ok(map);
        }

        if (source == 1) {
            tradeOrderDTO.setTradeType(OrderEnums.TradeType.APP);
        }

        //支付超时
        taskScheduler.schedule(() -> payService.payTimeout(orderPO.getOrderId()), Jsr310Utils.DateTime.toDate(orderPO.getPayExpireTime()));

        return ApiResult.ok(wechatPayService.JsApiBizPackage(tradeOrderDTO, request));
    }

    /**
     * 去支付
     *
     * @param orderId 订单号
     * @param source  来源0 小程序  1 APP
     * @param request
     * @return
     */
    @ApiOperation("去支付")
    @GetMapping("/toPay/{orderId}")
    public ApiResult toPay(@CurrentUser UserPO user, @PathVariable("orderId") String orderId,
                           @RequestParam(required = false, defaultValue = "0") Integer source,
                           HttpServletRequest request) {
        //去支付
        WxTradeOrderDTO tradeOrderDTO = payService.pay(orderId);
        if (source == 1) {
            tradeOrderDTO.setTradeType(OrderEnums.TradeType.APP);
        } else {
            if (tradeOrderDTO != null) {
                //重新获取用户最新的openID
                tradeOrderDTO.setOpenId(user.getWechatUser().getOpenId());
            }
        }
        return ApiResult.ok(wechatPayService.JsApiBizPackage(tradeOrderDTO, request));
    }

    /**
     * 订单列表
     *
     * @param condition
     * @param page
     * @param size
     * @return
     */
    @ApiOperation("订单列表")
    @PostMapping("/search/pageSearch")
    public ApiResult orderList(
            @CurrentUser UserPO user,
            OrderSearchCondition condition,
            @RequestParam(required = false, defaultValue = "1") Integer page,
            @RequestParam(required = false, defaultValue = "20") Integer size) {

        if (condition.getMerchantId() <= 0) {
            condition.setUserId(user.getUserId());
        }
        Page<SubOrderPO> pageData = subOrderService.findAll(page, size, condition);

        PageDataVO<SubOrderVO> pageDataVO = new PageDataVO<>();
        pageDataVO.setPageSize(size);
        pageDataVO.setPageIndex(page);
        pageDataVO.setPageCount(pageData.getTotalPages());
        pageDataVO.setTotal(pageData.getTotalElements());

        List<SubOrderVO> list = OrderMapStruct.Instance.suOrderPO2SuOrderVOS(pageData.getContent());

        list.forEach(order -> order.getOrderItem().forEach(item -> {
            GoodsInfoVO goodsInfo = item.getGoodsInfo();
            if (!StringUtilsExt.isURl(goodsInfo.getThumbnail())) {
                goodsInfo.setThumbnail(resourceService.getUrl(goodsInfo.getThumbnail()));
                item.setGoodsInfo(goodsInfo);
            }
        }));
        pageDataVO.setRows(list);
        return ApiResult.ok(pageDataVO);
    }

    /**
     * 售后订单列表
     *
     * @param condition
     * @param page
     * @param size
     * @return
     */
    @ApiOperation("售后订单列表")
    @PostMapping("/aftersale/list")
    public ApiResult aftersaleList(@CurrentUser UserPO user,
                                   AfterSaleCondition condition,
                                   @RequestParam(required = false, defaultValue = "1") Integer page,
                                   @RequestParam(required = false, defaultValue = "20") Integer size) {
        if (condition.getMerchantId() <= 0) {
            condition.setUserId(user.getUserId());
        }
        Page<AfterSaleBillPO> pageData = afterSaleService.findAll(page, size, condition);
        PageDataVO<AfterSaleBillVO> pageDataVO = new PageDataVO<>();
        pageDataVO.setPageSize(size);
        pageDataVO.setPageIndex(page);
        pageDataVO.setPageCount(pageData.getTotalPages());
        pageDataVO.setTotal(pageData.getTotalElements());
        pageDataVO.setRows(OrderMapStruct.Instance.po2AfterSaleBillVOS(pageData.getContent()));
        return ApiResult.ok(pageDataVO);
    }

    /**
     * @param afterSaleId 售后ID
     * @return
     */
    @ApiOperation("售后详情")
    @PostMapping("/aftersale/detail/{afterSaleId}")
    public ApiResult afterSaleDetail(@PathVariable("afterSaleId") String afterSaleId) {
        AfterSaleBillPO po = afterSaleService.findById(afterSaleId);
        if (po != null) {
            SubOrderPO subOrderPO = subOrderService.findById(po.getSubOrderId());
            SubOrderVO subOrderVO = OrderMapStruct.Instance.suOrderPO2SuOrderVO(subOrderPO);
            subOrderVO.setAfterSaleId(po.getId());
            subOrderVO.setRemark(po.getRemark());
            subOrderVO.setAfterSaleFinishTime(po.getUpdateTime());
            subOrderVO.setAfterSaleApplyTime(po.getCreateTime());
            return ApiResult.ok(subOrderVO);
        }
        return ApiResult.error("无效售后单");
    }


    /**
     * 订单详情
     *
     * @param user
     * @param orderId 订单号
     * @return
     */
    @ApiOperation("订单详情")
    @GetMapping("/detail/{orderId}")
    public ApiResult detail(@CurrentUser UserPO user, @PathVariable("orderId") String orderId) {
        SubOrderPO subOrderPO = subOrderService.findById(orderId);
        SubOrderVO order = OrderMapStruct.Instance.suOrderPO2SuOrderVO(subOrderPO);
        if (order == null) {
            return ApiResult.error("订单不存在");
        }
        order.getOrderItem().forEach(item -> {
            GoodsInfoVO goodsInfo = item.getGoodsInfo();
            if (!StringUtilsExt.isURl(goodsInfo.getThumbnail())) {
                goodsInfo.setThumbnail(resourceService.getUrl(goodsInfo.getThumbnail()));
                item.setGoodsInfo(goodsInfo);
            }
        });
        /**
         * 获取第三方交易单号
         */
        if (StringUtils.isNotBlank(order.getPaymentBillId())) {
            PaymentBillPO po = paymentBillService.findById(order.getPaymentBillId());
            if (po != null && StringUtils.isNotBlank(po.getThirdTradingNo())) {
                order.setThirdTradingNo(po.getThirdTradingNo());
            }
        }

        if (order.getAfterSaleStatus() != null) {
            order.setAfterSaleFinishTime(subOrderPO.getOrderItemPOS().get(0).getAfterSaleFinishTime());
            order.setAfterSaleId(subOrderPO.getOrderItemPOS().get(0).getAfterSaleId());
        }

        return ApiResult.ok(order);
    }

    /**
     * 删除订单
     *
     * @param user
     * @param orderId
     * @return
     */

    @PutMapping("/deleted/{orderId}")
    public ApiResult deleted(@CurrentUser UserPO user, @PathVariable("orderId") String orderId) {
        return ApiResult.ok();

    }

    /**
     * 取消订单
     *
     * @param user
     * @param orderId
     * @return
     */
    @PutMapping("/closed/{orderId}")
    public ApiResult closed(@CurrentUser UserPO user, @PathVariable("orderId") String orderId) {
        return ApiResult.ok();
    }


    /**
     * 用户签收/确认收货
     *
     * @param user
     * @param orderId
     * @return
     */
    @ApiOperation("用户签收/确认收货")
    @PutMapping("/signReceive/{orderId}")
    public ApiResult signReceive(@CurrentUser UserPO user, @PathVariable("orderId") String orderId) {
        deliverService.receiveByUser(orderId);
        return ApiResult.ok();
    }

    /**
     * 提交退货物流信息
     *
     * @param user
     * @param orderId
     * @param data    售后参数
     * @return
     */
    @PutMapping("/returnsOrder/{orderId}")
    public ApiResult returnsOrder(@CurrentUser UserPO user, @PathVariable("orderId") String orderId, Object data) {
//        AfterSaleSaveDTO dto = new AfterSaleSaveDTO();
//        if (afterSaleService.save(dto) != null) {
//            return ApiResult.ok();
//        }

        return ApiResult.error("操作失败");

    }

    /**
     * 发起售后
     *
     * @param user
     * @param suOrderId 订单号
     * @param dto       售后参数
     * @return
     */
    @ApiOperation("发起售后")
    @PostMapping("/afterSales/{orderId}")
    public ApiResult afterSales(@CurrentUser UserPO user, @PathVariable("orderId") String suOrderId, AfterSaleSaveDTO dto) {
        SubOrderPO po = subOrderService.findById(suOrderId);
        if (po != null && po.getOrderItemPOS().size() > 0) {
            dto.setOrderItemId(po.getOrderItemPOS().get(0).getId());
            dto.setUserId(user.getUserId());
            if (afterSaleService.save(dto) != null) {
                return ApiResult.ok();
            }
        }
        return ApiResult.error("操作失败");
    }

    /**
     * 查看物流
     *
     * @param suOrderId
     * @return
     */
    @ApiOperation("查看物流")
    @GetMapping("/queryTrack/{orderId}")
    public ApiResult queryTrack(@PathVariable("orderId") String suOrderId) {
        List<DeliverBillPO> billPOS = deliverService.findByOrder(suOrderId);
        if (billPOS != null && billPOS.size() > 0) {
            DeliverBillPO deliverBillPO = billPOS.get(0);
            LogisticsVO vo = new LogisticsVO();
            vo.setExpressCom(deliverBillPO.getExpressCom());
            vo.setExpressNo(deliverBillPO.getExpressNo());
            List<LogisticsDataVO> list = new ArrayList<>();
            LogisticsDataVO data = new LogisticsDataVO();
            data.setContext("包裹正在等待揽收");
            data.setTime(deliverBillPO.getCreateTime().toString());
            data.setStatus("已发货");
            ApiResult apiResult = provider.query(deliverBillPO.getExpressComCode(), deliverBillPO.getExpressNo());
            if (apiResult.isSuccess()) {
                list.addAll((List<LogisticsDataVO>) apiResult.getData());
            }
            list.add(data);
            vo.setData(list);
            return ApiResult.ok(vo);
        }
        return ApiResult.error("暂无发货记录");
    }


    @ApiOperation("发货")
    @PostMapping("/deliver/{subOrderId}")
    public ApiResult deliver(@CurrentUser UserPO user, @PathVariable("subOrderId") String subOrderId, DeliverDTO deliverDTO) {
        deliverDTO.setFreightAmount(BigDecimal.ZERO);
        deliverDTO.setOrderId(subOrderId);
        subOrderService.deliver(deliverDTO, user.getMerchant());
        return ApiResult.resultWith(ResultCodeEnum.SUCCESS);
    }


    @ApiOperation("同意售后")
    @PostMapping("/afterSales/approve/{id}")
    public ApiResult approve(@CurrentUser UserPO user, @PathVariable("id") String id) {
        checkMerchant(user, id);
        afterSaleService.approve(id);
        return ApiResult.ok();
    }

    @ApiOperation("拒绝售后")
    @PostMapping("/afterSales/refuse/{id}")
    public ApiResult refuse(@CurrentUser UserPO user, @PathVariable("id") String id) {
        checkMerchant(user, id);
        afterSaleService.refuse(id, "");
        return ApiResult.ok();
    }

    @ApiOperation("退款")
    @PostMapping("/afterSales/refund/{id}")
    public ApiResult refund(@CurrentUser UserPO user, @PathVariable("id") String id) {
        checkMerchant(user, id);
        afterSaleService.refund(id, OrderEnums.RefundType.ORIGINAL_WAY.getCode());
        return ApiResult.ok();
    }


    private void checkMerchant(UserPO user, String id) {
        AfterSaleBillPO afterSaleBillPO = afterSaleService.findById(id);
        if (afterSaleBillPO == null || !afterSaleBillPO.getMerchantPO().getMerchantId().equals(user.getMerchantId())) {
            throw new ApiException("无权限");
        }
    }

}
